import xml.etree.ElementTree as ET
import openpyxl
import argparse
import time
import re

"""
git推送学习：https://cloud.tencent.com/developer/article/1862274
2.测试用例转化学习：
a.不能tc套tc，tc是最小单元
b.新版freemind-v1.2.1版本：新版本已提交，现支持通过表头动态识别关键内容所在列，使用更为灵活
c.使用中需要注意的地方

1.使用上述的freemind-v1.2.1版本，将该文件新建项目后放置在项目中，将爱智测试用例模板也放入项目中，

2..执行命令：python freemind-v1.0.0.py -i 小智快存-回收站.mm -o 爱智测试用例模版.xlsx

3.然后去看这个爱智测试用例模板.xls打开即可看到转化的测试用例

4.相关参数的说明：
a.产品（最开头的地方）  要写这个产品的名称  如  爱智家
b.模块（产品引申出来），会在测试用例模板的倒数第几列
，诸如 爱智家-设置
c.测试点（产品引申出来），随后的每次引申都是测试点，直到你看到tc， 分一级  二级 可以自由延伸即可  会自动填写进去的，分别是1级测试点/2级测试点 等等
d.测试目的（测试点引申出来且需要标注为tc:），就是用一句话来说明你这个用例是干嘛的， 就是在最后一级测试点结束的地方 引申出来 tc: 
随后引申同级的节点都是相关的步骤
tp:前置条件   例如1、     2、   
ts:步骤描述  例如1、    2、  
tr:预期结果   
tl:优先级，可以直接写，例如P0       
ta:隶属，诸如EdgerOs       
tb:用例来源，诸如测试设计


例子
                tp   前置条件
                ts   步骤
                tr   预期结果
                tl   优先级
                ta   隶属
a-b-c1-d1-e1-tc-tb   用例来源
   -c2
   -c3
"""
parser = argparse.ArgumentParser()

# 定义一个输入文件
parser.add_argument('-i', '--input', type=str, dest='inputfile', default='小智快存_modified.mm',
                    help='Default inputfile is a freemind file like test.mm')
# 定义一个更新的模块
parser.add_argument('-m', '--modify', type=str, dest='modifymodel', default='节点管理',
                    help='Default modifymodel is a project or model like ECSM or Nas')
# 定义一个输出文件
parser.add_argument('-o', '--output-file', type=str, dest='outputfile', default='./爱智测试用例模板.xlsx',
                    help='Default outputfile is a excel lile 云原生测试用例.xlsx')
args = parser.parse_args()

# 读取工作簿
wb = openpyxl.load_workbook(args.outputfile)
# 确立当前工作表
ws = wb.active
# 确认最大行数
row_st = ws.max_row
row = ws.max_row


def set_row():
    """
    全局声明一个行的变量，用于多条用例自动换行
    :return:
    """
    global row
    row = row + 1


def perf_func(elem, func1, func2, level=0):
    """
    读取树状结构的方法
    :param elem: xml元素
    :param func1: 层级函数复用
    :param func2: 写入函数复用
    :param level: 打印当前层级
    :return:
    """
    func1(elem, level, func2)
    for child in elem.findall("node"):  # 遍历获取所有子节点
        perf_func(child, func1, func2, level + 1)


def print_level(elem, level, func2):
    """
    输出感官更明显的层级关系
    :param elem: xml元素
    :param level: 层级
    :param func2: 函数复用
    :return:
    """
    name = elem.get('TEXT')  # 获取子节点的文本值
    if name is not None:
        func2(level, name)


def draw_value(value):
    """
    切割标记位与内容的方法
    :param value:
    :return:
    """
    split = value[3:]
    return split


def wrap_value(value):
    value = draw_value(value)
    # print(value)
    tmp_list = re.split(r'[1-9]、', value)
    while ' ' in tmp_list:
        tmp_list.remove(' ')
    while '' in tmp_list:
        tmp_list.remove('')
    n = 1
    value = ''
    for i in tmp_list:
        value = value + '%s、' % n + i + '\n'
        n = n + 1
    # print(value)
    return value


def get_module(ws, title):
    c = 1
    for i in ws[1]:
        if i.value == title:
            break
        c = c + 1
    return c


def write_excel(level=0, value=None):
    """
    将读取到的数据写入指定excel文件
    :param level:
    :param value:
    :return:
    """
    test_ele_list = []  # 建立一个空表格，装载多级测试点
    r_level = 0
    m_col = get_module(ws, '模块')
    tc_col = get_module(ws, '测试目的')
    tf_col = get_module(ws, '一级测试点')
    tp_col = get_module(ws, '前置条件')
    ts_col = get_module(ws, '步骤描述')
    tr_col = get_module(ws, '预期结果')
    tl_col = get_module(ws, '优先级')
    ta_col = get_module(ws, '隶属')
    tb_col = get_module(ws, '用例来源')
    if level == 1:  # 第一级写入产品列
        ws.cell(row=row + 1, column=2, value=value)
    elif level == 2:  # 第二级直接写入 模块列
        ws.cell(row=row + 1, column=m_col, value=value)
    elif value.startswith('tc'):  # 当有 tc 标记时，直接写入 测试目的列
        set_row()
        ws.cell(row=row, column=tc_col, value=draw_value(value))
        # print("tc----%s---value--%s"%(row,draw_value(value)))
        r_level = level
    elif value.startswith('tp'):  # 当有 tp 标记时，直接写入 前置条件列
        ws.cell(row=row, column=tp_col, value=wrap_value(value))
        # print("tp----%s---value--%s"%(row,draw_value(value)))
    elif value.startswith('ts'):  # 当有 ts 标记时，直接写入 测试步骤列
        ws.cell(row=row, column=ts_col, value=wrap_value(value))
        # print("ts----%s---value--%s"%(row,draw_value(value)))
    elif value.startswith('tr'):  # 当有 tr 标记时，直接写入 预期结果列
        ws.cell(row=row, column=tr_col, value=wrap_value(value))
        # print("tr----%s---value--%s"%(row,draw_value(value)))
    elif value.startswith('tl'):  # 当有 tl 标记时，直接写入 优先级列
        ws.cell(row=row, column=tl_col, value=draw_value(value))
        # print("tl----%s---value--%s"%(row,draw_value(value)))
    elif value.startswith('ta'):  # 当有 ta 标记时，直接写入 隶属列
        value1 = draw_value(value)
        value2 = value1.replace("|", ",")
        ws.cell(row=row, column=ta_col, value=value2)
        # print("ta----%s---value--%s" % (row, draw_value(value)))
    elif value.startswith('tb'):  # 当有 tb 标记时，直接写入 用例来源列
        ws.cell(row=row, column=tb_col, value=draw_value(value))
        # print("tb----%s---value--%s" % (row, draw_value(value)))
    else:
        ws.cell(row=row + 1, column=tf_col - 3 + level, value=value)
        # print(f"在第{row+1}行{3+level}列写入了值{value}")
    if r_level == 0:
        pass
    else:
        for i in range(0, r_level - 3):
            value = ws.cell(row=row, column=i + tf_col).value
            if value is None:
                ws.cell(row=row, column=i + tf_col, value="占位")


def set_column(ws):
    """
    上述方法执行后，由于所属产品为父节点，会出现空值。此处将其补充完整
    :return:
    """
    c = get_module(ws, '模块')
    column_list1 = []
    column_list2 = []
    for k in range(2, row + 2):
        column_list1.append(ws.cell(k, 2).value)
        column_list2.append(ws.cell(k, c).value)
    for j in range(0, len(column_list1)):
        if column_list1[j] is None:
            column_list1[j] = column_list1[j - 1]
    for j in range(0, len(column_list2)):
        if column_list2[j] is None:
            column_list2[j] = column_list2[j - 1]
    v = 2
    for k in column_list1:
        ws.cell(v, 2, k)
        v = v + 1
    t = 2
    for j in column_list2:
        ws.cell(t, c, j)
        t = t + 1


def set_row_value():
    """
    补齐多级测试点下打开的不同分支前几级测试点
    :return:
    """
    time2 = time.time()
    # r = row_st + 1
    # while r <= row:  # 从新增的第一行开始循环遍历
    tf_col = get_module(ws, '一级测试点')
    for m in range(2, row + 1):
        for j in range(tf_col, tf_col + 6):
            if ws.cell(m, j).value == "占位":
                value = ws.cell(m - 1, j).value
                ws.cell(m, j, value)
        # r += 1

    print(f"循环花费时间{time.time() - time2}")
    m_row = ws.max_row
    ws.delete_rows(m_row)


time1 = time.time()
root = ET.parse(args.inputfile)  # 读取输入文件
try:
    r_list = []
    c_row = 1
    i = 0
    for i in range(1, ws.max_row + 1):
        if args.modifymodel == ws.cell(i, 2).value:
            r_list.append(i)
    r_list = sorted(r_list, reverse=True)
    for i in r_list:
        ws.delete_rows(i)
        print(f"删除了{i}行")
except Exception as e:
    print(e)

wb.save(args.outputfile)  # 保存该工作簿
# 重新读取工作簿
wb = openpyxl.load_workbook(args.outputfile)
# 重新获取当前工作表
ws = wb.active
# 重新确认最大行数
row_st = ws.max_row
row = ws.max_row
# 多级测试点的起始列

perf_func(root.getroot(), print_level, write_excel)  # 循环调用方法写入 excel 文件中
set_column(ws)  # 补充完成模块值
set_row_value()
wb.save(args.outputfile)  # 输出并保存工作簿到指定文件中
print("用例输出完成，请及时导入多维表格中")
print(time.time() - time1)
